package com.cxx.purchasecharge.core.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.cxx.purchasecharge.core.config.CxxProperties;
import com.cxx.purchasecharge.core.config.CxxPropertiesFactory;
import com.cxx.purchasecharge.core.util.CoreConstants;
import com.cxx.purchasecharge.core.util.StringUtil;

/**
 * Provides an implementation of the ICryptoKey interface.  This will read the key from
 * the keystore file in the common directory.  The details to read the key store are
 * in the cryptokeys configuration file.
 */
public class CryptoKeyFromKeyStore implements ICryptoKey
{
    private static final Logger logger = Logger.getLogger(CryptoKeyFromKeyStore.class);
    private static final String PROP_GROUP = "cryptokeys";
    private static final String PROP_PREFIX = "keystore.";
    private static final String PROP_FILE = "file";
    private static final String PROP_ALIAS = "alias";
    private static final String PROP_STORE_PASS = "storePass";
    private static final String PROP_KEY_PASS = "keyPass";
    
    private Key m_key;
    private boolean m_init = false;
    
    private void init() throws CryptoException
    {
        try
        {
            CxxProperties cfgProp = CxxPropertiesFactory.getInstance ().getProperties (PROP_GROUP);
            if ( cfgProp != null)
            {
                Properties prop = cfgProp.getSubProperties (PROP_PREFIX);
                if ( prop != null)
                {
                    String fileName = prop.getProperty (PROP_FILE);
                    boolean badCfg = false;
                    if ( StringUtil.isNullOrBlank (fileName))
                    {
                        logger.warn (PROP_PREFIX + PROP_FILE +" is not found in "+ PROP_GROUP +" properties");
                        badCfg = true;
                    }
                    
                    String alias = prop.getProperty (PROP_ALIAS);
                    if ( StringUtil.isNullOrBlank (alias))
                    {
                        logger.warn (PROP_PREFIX + PROP_ALIAS +" is not found in "+ PROP_GROUP +" properties");
                        badCfg = true;
                    }
                    
                    String storePass = prop.getProperty (PROP_STORE_PASS);
                    if ( StringUtil.isNullOrBlank (storePass))
                    {
                        logger.warn (PROP_PREFIX + PROP_STORE_PASS +" is not found in "+ PROP_GROUP +" properties");
                        badCfg = true;
                    }
                    
                    String keyPass = prop.getProperty (PROP_KEY_PASS);
                    if ( StringUtil.isNullOrBlank (keyPass))
                    {
                        logger.warn (PROP_PREFIX + PROP_KEY_PASS +" is not found in "+ PROP_GROUP +" properties");
                        badCfg = true;
                    }
                    
                    if ( !badCfg)
                    {
                        String commonConfigDir = System.getProperty (CoreConstants.COMMON_PROPERTY_DIR);
                        File keystoreFile = new File(commonConfigDir + File.separator + "keystore" +
                                File.separator + fileName);
                        
                        if ( keystoreFile.exists ())
                        {
                            
                            final KeyStore keyStore = KeyStore.getInstance("JCEKS");
                            
                            final FileInputStream input   = new FileInputStream( keystoreFile );
                            keyStore.load( input, storePass.toCharArray () );
                            input.close();
                            
                            if ( keyStore.containsAlias (alias))
                            {
                                m_key = keyStore.getKey( alias, keyPass.toCharArray ());
                                m_init = true;
                            }
                            else
                            {
                                logger.warn ("Alias is not found: "+alias);
                            }
                            
                        }
                        else
                        {
                            logger.warn ("Unable to find file: "+keystoreFile.toString ());
                        }   
                    }
                    else
                    {
                        logger.warn("Unable to retrieve crypto keys from keystore");
                    }
                }
                else
                {
                    logger.warn("Unable to find prefix ("+PROP_PREFIX+") in config file: "+PROP_GROUP);
                    throw new CryptoException ("Unable to find prefix ("+PROP_PREFIX+") in config file: "+PROP_GROUP);
                }
            }
            else
            {
                logger.warn("Unable to find config file: "+PROP_GROUP);
                throw new CryptoException ("Unable to find config file: "+PROP_GROUP);
            }
        }
        catch (Exception e)
        {
            logger.warn("Unable to retrieve keys from keystore: "+PROP_GROUP,e);
            throw new CryptoException (e);
        }
    }
    /* (non-Javadoc)
     * @see net.carefx.crypto.ICryptoKey#getKey()
     */
    @Override
    public Key getKey ()
    {
        if ( ! m_init)
        {
            try
            {
                init();
            }
            catch (CryptoException e)
            {
                logger.warn ("Unable to create key", e);
            }
        }
            
        
        return m_key;
    }
    
}
